#include "stdafx.h"
#include "Errors.h"
#include "Environment.h"

namespace MiniBasic
{
    namespace Errors
    {
        static const char* const errorStrings[ERRORS_END] = 
        {
            "Syntax Error",
            "Number too large",
            "Invalid array index",
            "Out of memory",
            "TO expected after FOR",
            "Division by 0",
            "Expected an =",
            "Invalid line number",
            "Too many GOSUBs",
            "Invalid RETURN - not in a sub",
            "Variable already used in a different active for loop",
            "NEXT without FOR",
            "NEXT variable is different to the FOR variable",
            "Comma expected",
            "Parameters to built-in function are invalid",
            "Expected a variable",
            "Expected a number or numeric variable",
            "Internal failure in built-in function",
            "Dll filename given to USR cannot be opened",
            "Function name given to USR cannot be found"
        };

        ErrorSink& operator<<(ErrorSink& sink, ERROR_CONDITION common)
        {
            return sink << errorStrings[common];
        }

        ErrorSink::ErrorSink(const Environment* env) : env(env) {}

        ErrorSink::~ErrorSink()
        {
            if(!(stream.str().empty()))
            {
                std::string temp;
                env->DoOutput(temp);
                temp = stream.str();
                env->DoOutput(temp);
            }
        }

        std::string Win32ErrorString(mbint error)
        {
            LPSTR lpMsgBuf = NULL;
            std::string errorText;
            if(!FormatMessageA(
                FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                FORMAT_MESSAGE_FROM_SYSTEM |
                FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL,
                static_cast<DWORD>(error),
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                reinterpret_cast<LPSTR>(&lpMsgBuf),
                0, NULL))
            {
                errorText = "Failed to retrieve error string";
            }
            else
            {
                errorText = lpMsgBuf;
                LocalFree(lpMsgBuf);
            }
            return errorText;
        }
    }
}
